package com.joinway.framework.data.jdbc.repository

import groovy.sql.Sql

import java.lang.reflect.Field
import java.sql.ResultSetMetaData

import org.apache.commons.lang3.StringUtils
import org.slf4j.Logger
import org.slf4j.LoggerFactory

import com.joinway.framework.bean.domain.Domain
import com.joinway.framework.bean.domain.constant.SqlConstants
import com.joinway.framework.data.jdbc.bean.ColumnMapping
import com.joinway.framework.data.jdbc.repository.utils.JdbcDataFactory
import com.joinway.framework.data.jdbc.type.ColumnCase
import com.joinway.framework.extension.groovy.DomainUtils

abstract class AbstractTableRepository {

	private final static Logger log = LoggerFactory.getLogger(AbstractTableRepository)
	
	protected final static String FIND_METHOD_PREFIX = "findBy";
	
	protected final static List AST_FIELD_NAMES = ['class', 'toStringStyle'];
	
	public final Sql sqlClient;
	
	protected abstract Field getDomainField(String columnName, Class<?> domainClass);
	
	protected abstract Object createDomain(Class<?> domainClass, List<ColumnMapping> columnNames, Object row) throws Exception;
	
	public AbstractTableRepository(Sql sqlClient){
		this.sqlClient = sqlClient;
	}
	
	protected Closure getEachRowClosure(List records, Class domainClass = null){
		// key - column name; value - alias name
		List<ColumnMapping> columnNames = new LinkedList()
		
		def c = {
//			println "no is " + no
//			def domain = domainClass ? domainClass.newInstance() : new Domain()

			ResultSetMetaData m = it.getProperties().get("metaData")
			
			def fields = m.getProperties().get("metaData")
			
			int count = m.getColumnCount()
			
			for(int i = 1; i <= count; i++){
				columnNames << new ColumnMapping(originalColumnName:m.getColumnName(i), columnName:m.getColumnLabel(i))
			}
			
			def domain = createDomain(domainClass, columnNames, it)
			
			records.add(domain)
		}
	}
	
	/**
	 * 
	 * @param params
	 * @return
	 */
	protected def normalizeParams(def params){
		def args = params
		
		if(args){
			if(args instanceof Collection || args instanceof Object[]){
				args = new LinkedList(args.flatten())
			}else if(args instanceof Map){
				args = args
			}else{
				args = new LinkedList()
				args << params
			}
		}
		
		args
	}

	protected<T> T getFirst(List<T> list){
		list ? list.get(0) : null
	}
	
	protected List<Object> toList(Object...params){
		params ? params.flatten() as List : []
	}
	
}
